package com.atguigu.gmall.cart.service.impl;


import com.atguigu.gmall.cart.service.CartService;
import com.atguigu.gmall.common.constant.RedisConst;
import com.atguigu.gmall.common.util.DateUtil;
import com.atguigu.gmall.model.cart.CartInfo;
import com.atguigu.gmall.model.product.SkuInfo;
import com.atguigu.gmall.product.client.ProductFeignClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.BoundHashOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

@Service
public class CartServiceImpl implements CartService {

    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private ProductFeignClient productFeignClient;

    /**
     * 添加购物车
     *
     * @param skuId
     * @param userId
     * @param skuNum 1.  判断要添加的商品在购物车中是否存在。
     *               true:则数量相加
     *               false:则直接加入购物车
     *               2.  每次添加购物车的时候都会默认选择状态
     *               3.  保证放入商品的数据价格是最新的
     *               4.  排序规则:按照修改时间排序
     */
    @Override
    public void addToCart(Long skuId, String userId, Integer skuNum) {
        String cartKey = getCartKey(userId);

        CartInfo cartInfoExist = (CartInfo) this.redisTemplate.opsForHash().get(cartKey, skuId.toString());

        //判断
        if (cartInfoExist != null) {
            //  说明当前加入的购物项，在购物车中存在。
            cartInfoExist.setSkuNum(cartInfoExist.getSkuNum() + skuNum);

            //  判断如果选择状态是 1 则不需要赋值， 如果是0 才需要更改.
            if (cartInfoExist.getIsChecked().intValue() == 0) {
                //更改为1
                cartInfoExist.setIsChecked(1);
            }
            //  赋值实时价格数据.  cartPrice 只记录加入时的价格,购物车列表显示的是skuPrice
            cartInfoExist.setSkuPrice(productFeignClient.getSkuPrice(skuId));

            //  重新赋值一下修改时间.
            cartInfoExist.setUpdateTime(new Date());
        } else {
            //  加入购物项不存在的时候，
            cartInfoExist = new CartInfo();
            //  赋值操作。
            SkuInfo skuInfo = this.productFeignClient.getSkuInfo(skuId); // 有可能会从缓存中获取数据.
            // 商品ID
            cartInfoExist.setSkuId(skuInfo.getId());
            // 商品名称
            cartInfoExist.setSkuName(skuInfo.getSkuName());
            // 商品件数
            cartInfoExist.setSkuNum(skuNum);
            //  第一次添加到缓存的时候， 加入购物车的价格 与 实时价格应该一致。
            // 当前价格
            cartInfoExist.setSkuPrice(this.productFeignClient.getSkuPrice(skuId));
            // 购物车价格
            cartInfoExist.setCartPrice(this.productFeignClient.getSkuPrice(skuId));
            // 默认图片
            cartInfoExist.setImgUrl(skuInfo.getSkuDefaultImg());
            // 用户id
            cartInfoExist.setUserId(userId);
            // 当前创建时间
            cartInfoExist.setCreateTime(new Date());
            // 当前更新时间
            cartInfoExist.setUpdateTime(new Date());
        }
        //  放入缓存.
        this.redisTemplate.opsForHash().put(cartKey, skuId.toString(), cartInfoExist);
    }

    /**
     * 获取购物车key的方法
     *
     * @param userId
     * @return
     */
    private String getCartKey(String userId) {
        return RedisConst.USER_KEY_PREFIX + userId + RedisConst.USER_CART_KEY_SUFFIX;
    }

    /**
     * 创建查询购物车列表功能
     *
     * @param userId
     * @param userTempId
     * @return
     */
    @Override
    public List<CartInfo> getCartList(String userId, String userTempId) {

        //  声明一个购物车集合对象。
        List<CartInfo> cartInfoNoLoginList = new ArrayList<>();

        //  未登录.
        if (!StringUtils.isEmpty(userTempId)) {
            //  获取未登录购物车数据集合.
            String cartKey = this.getCartKey(userTempId);
            //  获取数据 hvals key;
            cartInfoNoLoginList = this.redisTemplate.opsForHash().values(cartKey);
        }

        //  排序未登录购物车集合数据. 1 登录  111 未登录.
        if (!CollectionUtils.isEmpty(cartInfoNoLoginList) && StringUtils.isEmpty(userId)) {
            cartInfoNoLoginList.sort((o1, o2) -> {
                //  调用时间比较的工具类
                return DateUtil.truncatedCompareTo(o2.getUpdateTime(), o1.getUpdateTime(), Calendar.SECOND);
            });
            //  返回未登录购物车集合数据.
            return cartInfoNoLoginList;

        }

        //---------------以上代码处理未登录数据-------------------------
        //---------------以下代码涉及到登录数据-------------------------

            //  查询购物车列表。
            //  登录，还是未登录。
            if (!StringUtils.isEmpty(userId)) {
                //  获取到登录购物车集合数据，先获取到登录购物车数据 key
                String cartKey = this.getCartKey(userId);
                //  根据 cartKey 来获取到登录集合数据.
                BoundHashOperations<String,String,CartInfo> boundHashOperations = this.redisTemplate.boundHashOps(cartKey);
                //  boundHashOperations.get(); 获取到value的！

                //  在登录的情况下判断未登录的购物车中有数据。

                if (!CollectionUtils.isEmpty(cartInfoNoLoginList)){
                    //编写合并的业务逻辑
                    cartInfoNoLoginList.stream().forEach(cartInfoNoLogin ->{
                        //  判断：是否有skuId ; 判断登录的skuId 与 未登录的skuId 是否相同。
                        //  判断 field 是否有相同的！
                        if (boundHashOperations.hasKey(cartInfoNoLogin.getSkuId().toString())){
                            CartInfo cartInfoLogin = boundHashOperations.get(cartInfoNoLogin.getSkuId().toString());
                            //  未登录 --> 登录合并。 数量合并.
                            cartInfoLogin.setSkuNum(cartInfoLogin.getSkuNum()+cartInfoNoLogin.getSkuNum());
                            //设置更新时间
                            cartInfoLogin.setUpdateTime(new Date());

                            //  合并的细节： 选中状态：
                            if (cartInfoNoLogin.getIsChecked().intValue()==1 && cartInfoLogin.getIsChecked().intValue()==0){
                                cartInfoLogin.setIsChecked(1);
                            }
                            //  将更新好的对象写入缓存.
                            boundHashOperations.put(cartInfoNoLogin.getSkuId().toString(),cartInfoLogin);
                        }else {
                            cartInfoNoLogin.setUserId(userId);
                            cartInfoNoLogin.setCreateTime(new Date());
                            cartInfoNoLogin.setUpdateTime(new Date());
                            boundHashOperations.put(cartInfoNoLogin.getSkuId().toString(),cartInfoNoLogin);
                        }
                    });
                }
                //  删除未登录购物车集合数据;
                this.redisTemplate.delete(this.getCartKey(userTempId));
                //  获取到合并之后的数据.
                List<CartInfo> cartInfoLoginList = boundHashOperations.values();

                //排序
                if (!CollectionUtils.isEmpty(cartInfoLoginList)){
                    cartInfoLoginList.sort((o1,o2)->{
                        return DateUtil.truncatedCompareTo(o2.getUpdateTime(),o1.getUpdateTime(), Calendar.SECOND);
                    });
                }
            //  返回登录之后的数据
            return cartInfoLoginList;
        }
        //  返回购物车集合。
        return new ArrayList<>();
    }

    /**
     * 修改选中状态.
     * @param skuId
     * @param isChecked
     * @param userId
     */
    @Override
    public void checkCart (Long skuId, Integer isChecked, String userId){
        //  先获取到缓存的key;
        String cartKey = this.getCartKey(userId);
        //  hget key field;
        CartInfo cartInfo = (CartInfo) this.redisTemplate.boundHashOps(cartKey).get(skuId.toString());

        //  hget key field;
        // CartInfo cartInfo = (CartInfo) this.redisTemplate.opsForHash().get(cartKey, skuId.toString());
        if (cartInfo != null) {
            cartInfo.setIsChecked(isChecked);
            //  修改之后的数据放入缓存.
            this.redisTemplate.boundHashOps(cartKey).put(skuId.toString(), cartInfo);
        }
    }

    /**
     * 删除购物车数据.
     * @param userId
     * @param skuId
     */
    @Override
    public void deleteCart(String userId, Long skuId) {
        //  先获取购物车的key
        String cartKey = this.getCartKey(userId);
        //  执行删除命令.
        this.redisTemplate.boundHashOps(cartKey).delete(skuId.toString());

    }

    /**
     * 筛选购物车清单
     * @param userId
     * @return
     */
    @Override
    public List<CartInfo> getCartCheckedList(String userId) {
        //  获取购物车的key
        String cartKey = this.getCartKey(userId);
        //获取列表
        List<CartInfo> cartInfoList = this.redisTemplate.opsForHash().values(cartKey);
        //  将符合条件的数据留下;
        List<CartInfo> cartInfoCheckedList = cartInfoList.stream().filter(cartInfo -> {
            //将选中的状态为1的数据留下
            return cartInfo.getCartPrice().intValue() ==1;
        }).collect(Collectors.toList());

        return cartInfoCheckedList;
    }

}